﻿using System;
using System.Collections.Generic;
using System.Text;
using HR.Appointments.Service.DisplayLists;
using HR.Appointments.Service.Tools;
using HR.Appointments.Service.ValueObjects;

namespace HR.Appointments.Service.FacadeUsers
{
    /// <summary>
    /// Class for employee users for the system.
    /// </summary>
    public class Employee : User
    {
        #region Constructors
        /// <summary>
        /// Initializes a new employee class
        /// </summary>
        public Employee() 
        {
        }
        #endregion

        #region Securitiy
        /// <summary>
        /// Gets companyid for registerd company
        /// </summary>
        /// <param name="username">login name for company</param>
        /// <param name="password">password for company</param>
        /// <returns>Returns 0 if no company is found, else returns companyId</returns>
        public int ValidCredentialsThenGetCompanyId(string username, string password)
        {
            var company = DAO.Instance.Company.GetCompanyByUser(username, password);
            if (company != null)
                return company.CompanyId;
            else
                return 0;
        }

        #endregion

        #region Get Methods
        /// <summary>
        /// Get all orders from a company by a specific date.
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="date">Booking date of the orders</param>
        /// <returns>A list of orders</returns>
        public List<OrderList> GetOrdersByDate(int companyId, DateTime date)
        {
            return CalendarBook.Open(companyId, date).GetOrders();
        }

        /// <summary>
        /// Gets all orders for a specific company
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <returns>A list of orders</returns>
        public List<OrderList> GetAllOrders(int companyId)
        {
            var result = new List<OrderList>();
            foreach(OrderEntity obj in DAO.Instance.Order.GetAllValidOrders(companyId))
            {
                result.Add(new OrderList(obj));
            }
            return result;
        }
        
        /// <summary>
        /// Gets all reserved time for a specific company which 
        /// date has not passed (greatar og equal of DateTime.Today)
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <returns>A list of reserved time</returns>
        public List<ReservedTimeEntity> GetReservedTime(int companyId)
        {
            return DAO.Instance.ReservedTime.GetByCompanyId(companyId);
        }

        /// <summary>
        /// Get an instance of an activity
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="activityId">Activiti identifier</param>
        /// <returns></returns>
        public ActivityEntity GetActivityInstance(int companyId, int activityId)
        {
            return DAO.Instance.Activity.GetInstance(activityId);
        }

        /// <summary>
        /// Get an instance of a workstation
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="workstationId">Workstation identifier</param>
        /// <returns></returns>
		public WorkstationEntity GetWorkstationInstance(int companyId, int workstationId)
		{
			return DAO.Instance.Workstation.GetInstance(workstationId);
		}
        #endregion

        #region Create Methods
        /// <summary>
        /// Inserts a new activity to the database
        /// </summary>
        /// <param name="activity">A new activity entity</param>
        public void CreateActivity(ActivityEntity activity)
        {
            try
            {
                DAO.Instance.Activity.Insert(activity);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Insert activity failed", ex);
            }
        }

        /// <summary>
        /// Inserts a new workstation to the database
        /// </summary>
        /// <param name="workstation">A new workstation entity</param>
        public void CreateWorkstation(WorkstationEntity workstation)
        {
            try
            {
                DAO.Instance.Workstation.Insert(workstation);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Insert workstaion failed", ex);
            }
        }

        /// <summary>
        /// Inserts a new reservedtime to the database
        /// </summary>
        /// <param name="reservedTime">A new reservedtime entity</param>
        public void CreateReservedTime(ReservedTimeEntity reservedTime)
        {
            try
            {
                DAO.Instance.ReservedTime.Insert(reservedTime);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Insert reservedtime failed", ex);
            }

        }

        /// <summary>
        /// Inserts a new order to the database and marks it confirmed.
        /// </summary>
        /// <param name="order">A new order entity</param>
        public void BookOrder(OrderEntity order)
        {
            System.Diagnostics.Debug.Assert(order != null, "Order Entity is null");
            order.Status = OrderStatus.CONFIRMED;
            try
            {
                DAO.Instance.Order.Insert(order);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Insert order failed", ex);
            }
        }
        #endregion

        #region Update Methods
        /// <summary>
        /// Updates a activity to the database
        /// </summary>
        /// <param name="activity">A loaded activity entity</param>
        public void UpdateActivity(ActivityEntity activity)
        {
            try
            {
                DAO.Instance.Activity.Update(activity);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Update activity failed", ex);
            }
        }

        /// <summary>
        /// Updates a workstation to the database
        /// </summary>
        /// <param name="workstation">A loaded workstaion entity</param>
        public void UpdateWorkstation(WorkstationEntity workstation)
        {
            try
            {
                DAO.Instance.Workstation.Update(workstation);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Update workstation failed", ex);
            }
        }

        /// <summary>
        /// Updates a company to the database
        /// </summary>
        /// <param name="company">A loaded company entity</param>
        public void UpdateCompany(CompanyEntity company)
        {
            try
            {
                DAO.Instance.Company.Update(company);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Update company failed", ex);
            }
        }

        /// <summary>
        /// Updates all 7 days in openhour hour to the database for a specific company
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="fromTime">Time when to open the company</param>
        /// <param name="toTime">Time when to close the company</param>
        /// <param name="allDays">True if all days, else only working days</param>
        public void UpdateOpenHours(int companyId, TimeUnit fromTime, TimeUnit toTime, bool allDays)
        {
            foreach (OpenHoursEntity openHour in DAO.Instance.OpenHours.GetByCompany(companyId))
            {
                if (!allDays &&
                    (DateUtils.IntToDayOfWeek(openHour.DayId) == DayOfWeek.Saturday ||
                    DateUtils.IntToDayOfWeek(openHour.DayId) == DayOfWeek.Sunday))
                {
                    openHour.FromTime = TimeUnit.Create(0, 0);
                    openHour.ToTime = TimeUnit.Create(0, 0);
                }
                else
                {
                    openHour.FromTime = fromTime;
                    openHour.ToTime = toTime;
                }

                DAO.Instance.OpenHours.Commit(openHour);
            }
        }
        #endregion

        #region Delete Methods
        /// <summary>
        /// Delete a specific activity from the database
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="activityId">Activity identifier</param>
        public void DeleteActivity(int companyId, int activityId)
        {
            try
            {
                DAO.Instance.Activity.Delete(companyId, activityId);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Delete activity failed", ex);
            }
            
        }

        /// <summary>
        /// Delete a specific workstation from the database
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="workstationId">Workstation identifier</param>
        public void DeleteWorkstation(int companyId, int workstationId)
        {
            try
            {
			    DAO.Instance.Workstation.Delete(companyId, workstationId);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Delete workstation failed", ex);
            }
        }

        /// <summary>
        /// Delete a specific company from the database
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        public void DeleteCompany(int companyId)
        {
            try
            {
                DAO.Instance.Company.Delete(companyId);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Delete company failed", ex);
            }
        }

        /// <summary>
        /// Delete a specific order from the database
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="orderId">Order identifier</param>
		public void DeleteOrder(int companyId, int orderId)
		{
            try
            {
                DAO.Instance.Order.Delete(companyId, orderId);
            }
            catch (System.Data.SqlClient.SqlException ex)
            {
                throw new SubmitException("Delete order failed", ex);
            }
        }

        /// <summary>
        /// Delete a specific reserved time from the database
        /// </summary>
        /// <param name="reservedTimeId">Reservedtime identifier</param>
        public void DeleteReservedTime(int reservedTimeId)
		{
			try
			{
                DAO.Instance.ReservedTime.Delete(reservedTimeId);
			}
			catch (System.Data.SqlClient.SqlException ex)
			{
				throw new SubmitException("Delete reservedtime failed", ex);
			}
		}
        #endregion

        #region Mark Orders
        /// <summary>
        /// Markes the order as confirmed and saved it to the database
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="orderId">Order identifier</param>
        public void ConfirmOrder(int companyId, int orderId)
        {
            var order = DAO.Instance.Order.GetInstance(companyId, orderId);
            order.Status = OrderStatus.CONFIRMED;
            DAO.Instance.Order.Update(order);
        }

        /// <summary>
        /// Markes the order as denied and saved it to the database
        /// </summary>
        /// <param name="companyId">Company identifier</param>
        /// <param name="orderId">Order identifier</param>
        public void DenyOrder(int companyId, int orderId)
        {
            var order = DAO.Instance.Order.GetInstance(companyId, orderId);
            order.Status = OrderStatus.DENIED;
            DAO.Instance.Order.Update(order);
        }
        #endregion
    }
}
